package com.mustafaiev.tair.cts.service;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;

import com.mustafaiev.tair.cts.authentication.CostsTrackingSystemAuthToken;
import com.mustafaiev.tair.cts.dto.PayerDTO;
import com.mustafaiev.tair.cts.exeption.DataNotRetrievedException;
import com.mustafaiev.tair.cts.provider.CostsTrackingSystemAuthenticationProvider;
import com.mustafaiev.tair.exception.AuthenticationFailedException;

@Service
public class AuthenticationService {

	private static final Logger LOGGER = Logger
			.getLogger(CostsTrackingSystemAuthenticationProvider.class);

	@Autowired
	private PayerService payerService;

	public Authentication authenticate(final Authentication authentication)
			throws AuthenticationFailedException {

		UsernamePasswordAuthenticationToken systemAuthentication = null;
		systemAuthentication = getAuthenticationToken(authentication,
				systemAuthentication);
		return systemAuthentication;
	}

	private UsernamePasswordAuthenticationToken getAuthenticationToken(
			final Authentication authentication,
			final UsernamePasswordAuthenticationToken systemAuthentication)
			throws AuthenticationFailedException {
		final String pass = (String) authentication.getCredentials();
		return checkAuthentication(authentication, systemAuthentication, pass);
	}

	private UsernamePasswordAuthenticationToken checkAuthentication(
			final Authentication authentication,
			UsernamePasswordAuthenticationToken systemAuthentication,
			final String pass) throws AuthenticationFailedException {

		try {
			final PayerDTO payer = this.payerService
					.retrieveActiveByEmail(authentication.getPrincipal()
							.toString());

			final boolean isValidPassword = this.payerService.checkPassword(
					pass, payer.getPassword());
			if (isValidPassword) {
				systemAuthentication = doAuthenticate(authentication, payer);
			} else {
				throw new AuthenticationFailedException(
						"cts.error.auth.password.not.valid");
			}
		} catch (final DataNotRetrievedException e) {
			LOGGER.error(e.getLocalizedMessage());
			throw new AuthenticationFailedException(
					"cts.error.auth.user.not.found");
		}
		return systemAuthentication;
	}

	private UsernamePasswordAuthenticationToken doAuthenticate(
			final Authentication authentication, final PayerDTO payer) {

		UsernamePasswordAuthenticationToken systemAuthentication;
		final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();
		AUTHORITIES.add(payer.getRole());

		systemAuthentication = new CostsTrackingSystemAuthToken(payer,
				authentication.getCredentials(), AUTHORITIES);
		return systemAuthentication;
	}
}
